package net.aramzamzam.tapestry.judo.services.internal;

import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newSet;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.dom.Document;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;

public class Helper
{
    private final Set<String> _scripts = newSet();
    private final List<IncludedScript> _includedScripts = newList();

    private final StringBuilder _scriptOnDomLoadBlock = new StringBuilder();
    
    private final StringBuilder _scriptHeadBlock = new StringBuilder();
    
    private final StringBuilder _scriptBottomBlock = new StringBuilder();

    private final Set<String> _stylesheets = newSet();

    private final List<IncludedStylesheet> _includedStylesheets = newList();
    
    private class IncludedStylesheet
    {
        private final String _url;

        private final String _media;

        IncludedStylesheet(String url, String media)
        {
            _url = url;
            _media = media;
        }

        void add(Element head, int index)
        {
            head.elementAt(index, "link",

                           "href", _url,

                           "rel", "stylesheet",

                           "type", "text/css",

                           "media", _media);
        }
    }

    private class IncludedScript{
		private String url;
    	private String[] params;

    	public IncludedScript(String url, String[] params) {
			this.url = url;
			this.params = params;
		}
    	void add(Element head)
        {
     	   Vector<String> pa=new Vector<String>();
     	   //добавляем необходимые параметры
     	   pa.add("src");
     	   pa.add(url);
     	   pa.add("type");
     	   pa.add("text/javascript");
     	   //добавляем пользовательские параметры
     	   pa.addAll(Arrays.asList(params));
     	   //добавляем все это в head
            head.element("script", pa.toArray(new String[pa.size()]));
        }
    }
    
    public void addStylesheetLink(String styleURL, String media)
    {
        if (_stylesheets.contains(styleURL)) return;

        _includedStylesheets.add(new IncludedStylesheet(styleURL, media));

        _stylesheets.add(styleURL);
    }

    public void addScriptLink(String scriptURL, String... params)
    {
        if (_scripts.contains(scriptURL)) return;

        _includedScripts.add(new IncludedScript(scriptURL,params));
        
        _scripts.add(scriptURL);
    }

    public void addScriptOnDomLoad(String script)
    {
        if (InternalUtils.isBlank(script)) return;

        _scriptOnDomLoadBlock.append(script);
        _scriptOnDomLoadBlock.append("\n");
    }
    
    public void addScriptHead(String script)
    {
        if (InternalUtils.isBlank(script)) return;

        _scriptHeadBlock.append(script);
        _scriptHeadBlock.append("\n");
    }
    
    public void addScriptBottom(String script)
    {
        if (InternalUtils.isBlank(script)) return;

        _scriptBottomBlock.append(script);
        _scriptBottomBlock.append("\n");
    }

    public void addScript(String script, Element rootElement)
    {
        if (InternalUtils.isBlank(script)) return;

        Element e = rootElement.element("script", "type", "text/javascript");
        e.raw("\n<!--//\n");
        e.raw(script);
        e.raw("// -->\n");
    }

    public void writeScript(String script, MarkupWriter writer)
    {
    	Element e = writer.element("script", "type", "text/javascript");
    	e.raw("\n<!--\n");
        e.raw(script+"\n");
        e.raw("// -->\n");
        writer.end();
    }

    public void updateDocument(Document document)
    {
        Element root = document.getRootElement();

        // This can happen due to a catastrophic rendering error, such as a missing page template.
        if (root == null) return;

        // This only applies when the document is an HTML document. This may need to change in the
        // future, perhaps configurable, to allow for html and xhtml and perhaps others. Does SVG
        // use stylesheets?

        if (!root.getName().equals("html")) return;

        Element head = root.find("head");

        if (head == null) head = root.elementAt(0, "head");
        
        int stylesheets = _includedStylesheets.size();
        int count=0;
        if (stylesheets > 0)
        {

            for (int i=0; i < stylesheets; count++,i++)
                _includedStylesheets.get(i).add(head, count);
        }
        
        for (IncludedScript script : _includedScripts)
        	script.add(head);
        
        if (_scriptHeadBlock.length() > 0)
        {
            Element e = head.element("script", "type", "text/javascript");
            e.raw("\n<!--//\n");
            e.raw(_scriptHeadBlock.toString());
            e.raw("// -->\n");
        }

        
        
        Element body = root.find("body");

        if (body == null) return;

        if (_scriptBottomBlock.length() > 0)
        {
            Element e = body.element("script", "type", "text/javascript");
            e.raw("\n<!--//\n");

            e.raw( _scriptBottomBlock.toString());

            e.raw("// -->\n");
        }

        if (_scriptOnDomLoadBlock.length() > 0)
        {
            Element e = body.element("script", "type", "text/javascript");
            e.raw("\n<!--//\n");

            e.raw("judo.addOnLoad(function() {\n");

            e.raw(_scriptOnDomLoadBlock.toString());

            e.raw("});\n");

            e.raw("// -->\n");
        }
    }

}
